﻿
#define uthash_malloc zmalloc
#define uthash_free zfree

#include "support/uthash.h"
#include "ZUtils.h"
#include "ZColorMapValue.h"
#include "common/ZDpi.h"
#include "ZRenderer.h"

namespace ZuiLib
{

	const RECT  emptyRect={0,0,0,0};
	const POINT emptyPoint={0,0};
	const SIZE  emptySize={0,0};

	color_t TextToColor(const char* pstrValue)
	{
		while (*pstrValue > '\0' && *pstrValue <= ' ') 
			pstrValue = CharNext(pstrValue);

		if (*pstrValue == '#')
		{
			pstrValue = CharNext(pstrValue);
			char* pstr = NULL;
			return strtoul(pstrValue, &pstr, 16);
		}
		else if (*pstrValue<='9' && *pstrValue>='0')
		{
			char* pstr = NULL;
			return strtoul(pstrValue, &pstr, 10);
		}
		else
		{
			//颜色表
			ColorMapValue* colorValue= colorMap;
			while (colorValue->name)
			{
				if (stricmp(colorValue->name, pstrValue) == 0)
				{
					return colorValue->value | 0xff000000;
				}
				++colorValue;
			}
			return 0;
		}
	}

	const char* layoutText[] = {
		"none",
		"fill",//填充
		"left",//左边居中
		"top",
		"right",
		"bottom",
		"left_top",
		"right_top",
		"left_bottom",
		"right_bottom",
		"center",
	};

	const char* LayoutToText(LayoutType type)
	{
		return layoutText[type];
	}

	LayoutType TextToLayout(const char* text)
	{
		for (size_t i = 0; i < ZARRAY_SIZE(layoutText); i++)
		{
			if (strcmp(layoutText[i], text) == 0)
				return (LayoutType)i;
		}
		return LT_NONE;
	}

    int GetUTF8FromCodepoint(Uint32 nUChar, char* pszUTF8)
    {
        int nUTF8Len = 0;
        // Write UTF-8 sequence to pszUTF8 for Unicode code point nUChar and update nUTF8Len
        // Be sure pszUTF8 has room for up to 4 bytes
        if (!(nUChar & ~0x0000007f)) // < 0x80
        {
            if (pszUTF8)
                pszUTF8[nUTF8Len++] = (char)nUChar;
            else
                ++nUTF8Len;
        }
        else if (!(nUChar & ~0x000007ff)) // < 0x800
        {
            if (pszUTF8)
            {
                pszUTF8[nUTF8Len++] = (char)(((nUChar & 0x7c0) >> 6) | 0xc0);
                pszUTF8[nUTF8Len++] = (char)((nUChar & 0x3f) | 0x80);
            }
            else
                nUTF8Len += 2;
        }
        else if (!(nUChar & ~0x0000ffff)) // < 0x10000
        {
            if (pszUTF8)
            {
                pszUTF8[nUTF8Len++] = (char)(((nUChar & 0xf000) >> 12) | 0xe0);
                pszUTF8[nUTF8Len++] = (char)(((nUChar & 0xfc0) >> 6) | 0x80);
                pszUTF8[nUTF8Len++] = (char)((nUChar & 0x3f) | 0x80);
            }
            else
                nUTF8Len += 3;
        }
        else // < 0x110000
        {
            if (pszUTF8)
            {
                pszUTF8[nUTF8Len++] = (char)(((nUChar & 0x1c0000) >> 18) | 0xf0);
                pszUTF8[nUTF8Len++] = (char)(((nUChar & 0x3f000) >> 12) | 0x80);
                pszUTF8[nUTF8Len++] = (char)(((nUChar & 0xfc0) >> 6) | 0x80);
                pszUTF8[nUTF8Len++] = (char)((nUChar & 0x3f) | 0x80);
            }
            else
                nUTF8Len += 4;
        }

        if (pszUTF8)
            pszUTF8[nUTF8Len] = '\0';

        return nUTF8Len;
    }


    Uint32 GetCodepointFromUTF8(const char*& pszUTF8, const char* pszUTF8End/*=NULL*/)
    {
        // Return Unicode code point and increment pszUTF8 past 1-4 bytes
        // pszUTF8End can be NULL if pszUTF8 is null terminated
        Uint32 nUChar = (unsigned char)*pszUTF8;
        ++pszUTF8;
        if (nUChar & 0x80)
        {
            int nExtraChars;
            if (!(nUChar & 0x20))
            {
                nExtraChars = 1;
                nUChar &= 0x1f;
            }
            else if (!(nUChar & 0x10))
            {
                nExtraChars = 2;
                nUChar &= 0x0f;
            }
            else if (!(nUChar & 0x08))
            {
                nExtraChars = 3;
                nUChar &= 0x07;
            }
            else
                return -1;
            while (nExtraChars--)
            {
                if (pszUTF8 == pszUTF8End || !(*pszUTF8 & 0x80))
                    return -1;
                nUChar = nUChar << 6;
                nUChar |= *pszUTF8 & 0x3f;
                ++pszUTF8;
            }
        }
        return nUChar;
    }

    Uint32 GetCodepointFromUTF32(const Uint32*& pstr, const Uint32* pszEnd)
    {
        Uint32 codepoint = 0;
        if ((pszEnd && pstr < pszEnd) || *pstr)
        {
            codepoint = *pstr;
            ++pstr;
        }
        return codepoint;
    }

	bool PtInRect(const RECT* lprc,POINT lpt)
	{
		return (lpt.x <= lprc->right && lpt.x >= lprc->left && lpt.y <= lprc->bottom && lpt.y >= lprc->top);
	}

	bool SetRect(LPRECT lprc,int xLeft,int yTop,int xRight,int yBottom)
	{
		if(!lprc)
			return false;
		lprc->left=xLeft;
		lprc->top=yTop;
		lprc->right=xRight;
		lprc->bottom=yBottom;
		return true;
	}
	bool SetRectEmpty(LPRECT lprc)
	{
		if(!lprc)
			return false;
		lprc->left=0;
		lprc->top=0;
		lprc->right=0;
		lprc->bottom=0;
		return true;
	}
	bool CopyRect(LPRECT lprcDst,const RECT *lprcSrc)
	{
		if(!lprcDst || !lprcSrc)
			return false;
		lprcDst->left=lprcSrc->left;
		lprcDst->top=lprcSrc->top;
		lprcDst->right=lprcSrc->right;
		lprcDst->bottom=lprcSrc->bottom;
		return true;
	}
	bool InflateRect( LPRECT lprc, int dx, int dy)
	{
		if(!lprc)
			return false;
		lprc->left-=dx;
		lprc->right+=dx;
		lprc->top-=dy;
		lprc->bottom+=dy;
		return true;
	}

	bool IntersectRect(LPRECT lprcDst,const RECT *lprcSrc1,const RECT *lprcSrc2)
	{
		if (!lprcSrc1 || !lprcSrc2)
			return false;

		RECT rc;
		rc.left = SDL_max(lprcSrc1->left, lprcSrc2->left);
		rc.right = SDL_min(lprcSrc1->right, lprcSrc2->right);
		rc.top = SDL_max(lprcSrc1->top, lprcSrc2->top);
		rc.bottom = SDL_min(lprcSrc1->bottom, lprcSrc2->bottom);
		if (lprcDst)
			*lprcDst=rc;
		if (rc.left >= rc.right || rc.top >= rc.bottom)
		{
			return false;
		}
		else
			return true;
	}

	bool UnionRect(LPRECT lprcDst,const RECT *lprcSrc1,const RECT *lprcSrc2)
	{
		if (!lprcSrc1 || !lprcSrc2)
			return false;

		if (lprcSrc1->left==lprcSrc1->right || lprcSrc1->top==lprcSrc1->bottom)
		{
			*lprcDst=*lprcSrc2;
		}

		if (lprcSrc2->left==lprcSrc2->right || lprcSrc2->top==lprcSrc2->bottom)
		{
			*lprcDst=*lprcSrc1;
		}


		RECT rc;
		rc.left = SDL_min(lprcSrc1->left, lprcSrc2->left);
		rc.right = SDL_max(lprcSrc1->right, lprcSrc2->right);
		rc.top = SDL_min(lprcSrc1->top, lprcSrc2->top);
		rc.bottom = SDL_max(lprcSrc1->bottom, lprcSrc2->bottom);
		if (lprcDst)
			*lprcDst=rc;
		return true;
	}

    void InsetRect(LPRECT lprcDst, const RECT *lprcSrc)
    {
        lprcDst->left += lprcSrc->left;
        lprcDst->top += lprcSrc->top;
        lprcDst->right -= lprcSrc->right;
        lprcDst->bottom -= lprcSrc->bottom;
    }

	bool OffsetRect(LPRECT lprc,int dx,int dy)
	{
		if (!lprc)
			return false;
		lprc->left+=dx;
		lprc->right+=dx;
		lprc->top+=dy;
		lprc->bottom+=dy;
		return true;
	}

	bool IsRectEmpty(const RECT *lprc)
	{
		if (lprc)
			return lprc->right==lprc->left && lprc->top==lprc->bottom;
		else
			return false;
	}

	bool EqualRect(const RECT *lprc1,const RECT *lprc2)
	{
		if(!lprc1 || !lprc2)
			return false;
		return (lprc1->left==lprc2->left && lprc1->top==lprc2->top && lprc1->right==lprc2->right && lprc1->bottom==lprc2->bottom);
	}

	bool JoinRect(RECT *lpdst,const RECT *src)
	{
		if (!lpdst || !src)
			return false;
		if (lpdst->left==lpdst->right || lpdst->top==lpdst->bottom)
		{
			*lpdst=*src;
		}
		else
		{
			if( src->left < lpdst->left ) lpdst->left = src->left;
			if( src->top < lpdst->top ) lpdst->top = src->top;
			if( src->right > lpdst->right ) lpdst->right = src->right;
			if( src->bottom > lpdst->bottom ) lpdst->bottom = src->bottom;
		}
		return true;
	}

	bool ParserRect(RECT *lpdst,const char *src)
	{
		RECT rcPos = { 0 };
		char* pstr = NULL;
		rcPos.left = strtol(src, &pstr, 10);
		if (!pstr)
			return false;
		
        if (pstr[0] == 'd' && pstr[1] == 'p')
        {
            rcPos.left = _dpi_scale(rcPos.left);
            pstr += 2;
        }

		rcPos.top = strtol(pstr + 1, &pstr, 10);
		if (!pstr)
			return false;

        if (pstr[0] == 'd' && pstr[1] == 'p')
        {
            rcPos.top = _dpi_scale(rcPos.top);
            pstr += 2;
        }

		rcPos.right = strtol(pstr + 1, &pstr, 10);
		if (!pstr)
			return false;

        if (pstr[0] == 'd' && pstr[1] == 'p')
        {
            rcPos.right = _dpi_scale(rcPos.right);
            pstr += 2;
        }

		rcPos.bottom = strtol(pstr + 1, &pstr, 10);
		if (!pstr)
			return false;

        if (pstr[0] == 'd' && pstr[1] == 'p')
        {
            rcPos.bottom = _dpi_scale(rcPos.bottom);
            pstr += 2;
        }

		if (lpdst)
			*lpdst=rcPos;
		return true;
	}

	bool ParserSize(SIZE *lpdst,const char *src)
	{
		SIZE rcPos = { 0 };
		char* pstr = NULL;
		rcPos.cx = strtol(src, &pstr, 10);
		if (!pstr)
			return false;

		if (pstr[0] == 'd' && pstr[1] == 'p')
		{
				rcPos.cx = _dpi_scale(rcPos.cx);
				pstr += 2;
		}

		rcPos.cy = strtol(pstr + 1, &pstr, 10);
		if (!pstr)
			return false;

		if (pstr[0] == 'd' && pstr[1] == 'p')
		{
				rcPos.cy = _dpi_scale(rcPos.cy);
				pstr += 2;
		}

		if (lpdst)
			*lpdst=rcPos;
		return true;
	}

    bool ParserSize(int *lpdst, const char *src)
    {
        char* pstr = NULL;
        int x = strtol(src, &pstr, 10);
        if (!pstr)
            return false;

        if (pstr[0] == 'd' && pstr[1] == 'p')
        {
            x = _dpi_scale(x);
        }
        if (lpdst)
            *lpdst = x;
        return true;
    }

    int ParserSize(const char *src)
    {
        char* pstr = NULL;
        int x = strtol(src, &pstr, 10);
        if (!pstr)
            return false;

        if (pstr[0] == 'd' && pstr[1] == 'p')
        {
            x = _dpi_scale(x);
        }
        return x;
    }

    bool ParserPoint(POINT *lpdst, const char *src)
    {
        POINT rcPos = { 0 };
        char* pstr = NULL;
        rcPos.x = strtol(src, &pstr, 10);
        if (!pstr)
            return false;

        if (pstr[0] == 'd' && pstr[1] == 'p')
        {
            rcPos.x = _dpi_scale(rcPos.x);
            pstr += 2;
        }

        rcPos.y = strtol(pstr + 1, &pstr, 10);
        if (!pstr)
            return false;

        if (pstr[0] == 'd' && pstr[1] == 'p')
        {
            rcPos.y = _dpi_scale(rcPos.y);
            pstr += 2;
        }

        if (lpdst)
            *lpdst = rcPos;
        return true;
    }

    bool ParserBool(const char* src)
    {
        if (src && (strcmp(src, "true") == 0 || strcmp(src, "1") == 0))
            return true;
        else
            return false;
    }

    ZImageDrawInfo::ZImageDrawInfo() 
        :multiple(IMAGE_MULTIPLE_1), type(IMAGE_TYPE_FILE), 
        mask(0), rotate(0), layout(LT_FILL), loaded(false)
    {
        SetRectEmpty(&bmpPos);
        SetRectEmpty(&dest);
        SetRectEmpty(&scale9);
    }

    void ZImageDrawInfo::Clear()
    {
        multiple = IMAGE_MULTIPLE_1;
        type = IMAGE_TYPE_FILE;
        mask = 0;
        rotate = 0;
        layout = LT_FILL;
        loaded = false;
        drawString.Empty();
        image.Empty();

        SetRectEmpty(&bmpPos);
        SetRectEmpty(&dest);
        SetRectEmpty(&scale9);
    }

    ZImageDrawInfo::ZImageDrawInfo(const char* pstr)
    {
        *this = pstr;
    }

    #define SKIP_WHILE_SPACE(pStrImage) while( *pStrImage > '\0' && *pStrImage <= ' ' ) pStrImage = CharNext(pStrImage)


    const char* imageMultipleName[] = {
        "",
        "@1_5x",
        "@2x",
        "@3x"
    };

    bool ZImageDrawInfo::LoadImage(ZRenderer* render)
    {
        if (loaded)
            return true;
        if (image.IsEmpty())
            return false;

        //检测高dpi图片
        ImageMultiple imageScale = IMAGE_MULTIPLE_1;
        float dpiScale = ZDpi::Instance()->GetScaleValue();
        if (dpiScale >= 3)
        {
            imageScale = IMAGE_MULTIPLE_3;
        }
        else if (dpiScale >= 2)
        {
            imageScale = IMAGE_MULTIPLE_2;
        }
        else if (dpiScale >= 1.5)
        {
            imageScale = IMAGE_MULTIPLE_1_5;
        }

        int find = image.ReverseFind('.');
        ZTextureMgr* textMgr = render->GetTextureMgr();
        ZTextureAtlasMgr* textAtMgr = render->GetTextureAtlasMgr();

        for (int i = imageScale; i >= 0; --i)
        {
            ZString imageName = image;
            if (find >= 0)
                imageName.Insert(find, imageMultipleName[i]);
            else
                imageName.Append(imageMultipleName[i]);

            if (type == IMAGE_TYPE_FILE)
            {
                //加载文件
                if (textMgr->GetTextureEx(imageName))
                {
                    image = imageName;
                    multiple = (ImageMultiple)i;
                    loaded = true;
                    break;
                }
            }
            else
            {
                //加载atlas
                if (textAtMgr->GetAtlas(imageName))
                {
                    image = imageName;
                    multiple = (ImageMultiple)i;
                    loaded = true;
                    break;
                }
            }
        }

        if (!loaded)
            image.Empty();
        return loaded;
    }

    ZImageDrawInfo& ZImageDrawInfo::operator=(const char* pStrImage)
    {
        Clear();

        // 1、aaa.jpg
        // 2、file='aaa.jpg' res='' dest='0,0,0,0' source='0,0,0,0' corner='0,0,0,0' rotate='90'
        // mask='#FF0000'
        // layout= left right top bottom center lefttop hcenter
        drawString = pStrImage;
        ZString sItem;
        ZString sValue;
        char* pstr = NULL;

        while (*pStrImage != '\0') 
        {
            sItem.Empty();
            sValue.Empty();
            SKIP_WHILE_SPACE(pStrImage);
            while (*pStrImage != '\0' && *pStrImage != '=' && *pStrImage > ' ') 
            {
                const char* pstrTemp = CharNext(pStrImage);
                while (pStrImage < pstrTemp) {
                    sItem += *pStrImage++;
                }
            }
            SKIP_WHILE_SPACE(pStrImage);
            if (*pStrImage++ != '=') break;
            SKIP_WHILE_SPACE(pStrImage);
            if (*pStrImage++ != '\'') break;
            while (*pStrImage != '\0' && *pStrImage != '\'') {
                const char* pstrTemp = CharNext(pStrImage);
                while (pStrImage < pstrTemp) {
                    sValue += *pStrImage++;
                }
            }
            if (*pStrImage++ != '\'') 
                break;
            if (!sValue.IsEmpty()) 
            {
                if (sItem == "file") 
                {
                    image = sValue;
                    type = IMAGE_TYPE_FILE;
                }
                else if (sItem == "res") 
                {
                    image = sValue;
                    type = IMAGE_TYPE_ATLAS;
                }
                else if (sItem == "dest") 
                {
                    ParserRect(&dest, sValue.GetString());
                }
                else if (sItem == "source") 
                {
                    bmpPos.left = strtol(sValue.GetString(), &pstr, 10);
                    bmpPos.top = strtol(pstr + 1, &pstr, 10);
                    bmpPos.right = strtol(pstr + 1, &pstr, 10);
                    bmpPos.bottom = strtol(pstr + 1, &pstr, 10);
                }
                else if (sItem == "corner") 
                {
                    scale9.left = strtol(sValue.GetString(), &pstr, 10);
                    scale9.top = strtol(pstr + 1, &pstr, 10);
                    scale9.right = strtol(pstr + 1, &pstr, 10);
                    scale9.bottom = strtol(pstr + 1, &pstr, 10);
                }
                else if (sItem == "mask") 
                {
                    if (sValue[0] == '#')
                        mask = strtoul(sValue.GetString() + 1, &pstr, 16);
                    else
                        mask = strtoul(sValue.GetString(), &pstr, 16);
                }
                else if (sItem == "rotate") 
                {
                    rotate = strtol(sValue.GetString(), &pstr, 10);
                }
                else if (sItem == "layout") 
                {
                    LayoutType temp = TextToLayout(sValue);
                    if (temp != LT_NONE)
                    {
                        layout = temp;
                    }
                }
            }
            if (*pStrImage++ != ' ') break;
        }
        
        //没有配置属性,只有文件名
        if (image.IsEmpty() && sValue.IsEmpty())
        {
            image = sItem;
        }
        return *this;
    }


    ZImageDrawInfo& ZImageDrawInfo::operator=(const ZImageDrawInfo& info) 
    {
        drawString = info.drawString;
        image = info.image;
        multiple = info.multiple;
        type = info.type;
        CopyRect(&dest, &info.dest);
        CopyRect(&bmpPos, &info.bmpPos);
        CopyRect(&scale9, &info.scale9);
        mask = info.mask;
        rotate = info.rotate;
        layout = info.layout;
        loaded = info.loaded;
        return *this;
    }

    void ScaleRect(LPRECT dest, ZImageDrawInfo::ImageMultiple multiple)
    {
        static ZScale scaleLevel[] = { ZScale(1,1),ZScale(3,2),ZScale(2,1),ZScale(3,1) };

        ZScale scale = scaleLevel[multiple];
        dest->left = dest->left * scale.num / scale.den;
        dest->top = dest->top * scale.num / scale.den;
        dest->right = dest->right * scale.num / scale.den;
        dest->bottom = dest->bottom * scale.num / scale.den;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	ZPtrArray::ZPtrArray(int iPreallocSize)
	{
		m_impl.reserve(iPreallocSize);
	}

	ZPtrArray::ZPtrArray(const ZPtrArray& src)
		:m_impl(src.m_impl)
	{
		
	}
	ZPtrArray::~ZPtrArray()
	{

	}

	void ZPtrArray::Empty()
	{
		m_impl.clear();
	}
	void ZPtrArray::Resize(int iSize)
	{
		m_impl.resize(iSize);
	}
	bool ZPtrArray::IsEmpty() const
	{
		return  m_impl.empty();
	}

	int ZPtrArray::Find(data_t val) const
	{
		for (size_t i=0;i<m_impl.size();++i)
		{
			if (m_impl[i]==val)
			{
				return i;
			}
		}
		return -1;
	}

	void ZPtrArray::Add(data_t pData)
	{
		m_impl.push_back(pData);
	}


	bool ZPtrArray::SetAt(int iIndex, data_t pData)
	{
		if (iIndex<=GetSize())
		{
			m_impl[iIndex]=pData;
			return true;
		}
		else
			return false;
	}
	bool ZPtrArray::InsertAt(int iIndex, data_t pData)
	{
		if (iIndex<=GetSize())
		{
			m_impl.insert(m_impl.begin()+iIndex,pData);
			return true;
		}
		else
			return false;
	}
	bool ZPtrArray::Remove(int iIndex)
	{
		if(iIndex<GetSize() && iIndex>=0)
		{
			m_impl.erase(m_impl.begin()+iIndex);
			return true;
		}
		else
			return false;
	}

	bool ZPtrArray::Remove(const data_t ptr)
	{
		for (container_t::iterator i=m_impl.begin();i!=m_impl.end();++i)
		{
			if (*i==ptr)
			{
				m_impl.erase(i);
				return true;
			}
		}
		return false;
	}

	int ZPtrArray::GetSize() const
	{
		return m_impl.size();
	}
	ZPtrArray::data_t ZPtrArray::GetData()
	{
		return m_impl.front();
	}
	ZPtrArray::data_t ZPtrArray::GetAt(int iIndex) const
	{
		if(iIndex>=0 && iIndex<m_impl.size())
			return m_impl.at(iIndex);
		else
			return NULL;
	}
	ZPtrArray::data_t ZPtrArray::operator[] (int iIndex) const
	{
		return GetAt(iIndex);
	}

	ZPtrArray::data_t ZPtrArray::Front()const
	{
		return m_impl.front();
	}

	ZPtrArray::data_t ZPtrArray::Back()const
	{
		return m_impl.back();
	}





	ZRefPtrArray::ZRefPtrArray(int iPreallocSize)
	{
		m_impl.reserve(iPreallocSize);
	}

	ZRefPtrArray::ZRefPtrArray(const ZRefPtrArray& src)
		:m_impl(src.m_impl)
	{
		for (container_t::iterator i=m_impl.begin();i!=m_impl.end();++i)
		{
			(*i)->AddRef();
		}
	}

	ZRefPtrArray::~ZRefPtrArray()
	{
		for (container_t::iterator i=m_impl.begin();i!=m_impl.end();++i)
		{
			(*i)->Release();
		}
	}

	void ZRefPtrArray::Empty()
	{
		for (container_t::iterator i=m_impl.begin();i!=m_impl.end();++i)
		{
			(*i)->Release();
		}
		m_impl.clear();
	}
	void ZRefPtrArray::Resize(int iSize)
	{
		if (iSize<m_impl.size())
		{
			for (container_t::iterator i=m_impl.begin()+iSize;i!=m_impl.end();++i)
			{
				(*i)->Release();
			}
		}
		m_impl.resize(iSize);
	}

	bool ZRefPtrArray::IsEmpty() const
	{
		return  m_impl.empty();
	}

	int ZRefPtrArray::Find(data_t val) const
	{
		for (int i=0;i<m_impl.size();++i)
		{
			if (m_impl[i]==val)
			{
				return i;
			}
		}
		return -1;
	}

	void ZRefPtrArray::Add(data_t pData)
	{
		m_impl.push_back(pData);
		pData->AddRef();
	}


	bool ZRefPtrArray::SetAt(int iIndex, data_t pData)
	{
		if (iIndex<=GetSize())
		{
			pData->AddRef();
			m_impl[iIndex]->Release();
			m_impl[iIndex]=pData;
			return true;
		}
		else
			return false;
	}

	bool ZRefPtrArray::InsertAt(int iIndex, data_t pData)
	{
		if (iIndex<=GetSize())
		{
			pData->AddRef();
			m_impl.insert(m_impl.begin()+iIndex,pData);
			return true;
		}
		else
			return false;
	}

	bool ZRefPtrArray::Remove(int iIndex)
	{
		if(iIndex<GetSize() && iIndex>=0)
		{
			container_t::iterator i=m_impl.begin()+iIndex;
			(*i)->Release();
			m_impl.erase(i);
			return true;
		}
		else
			return false;
	}

	bool ZRefPtrArray::Remove(const data_t ptr)
	{
		for (container_t::iterator i=m_impl.begin();i!=m_impl.end();++i)
		{
			if (*i==ptr)
			{
				(*i)->Release();
				m_impl.erase(i);
				return true;
			}
		}
		return false;
	}

	int ZRefPtrArray::GetSize() const
	{
		return m_impl.size();
	}

	ZRefPtrArray::data_t ZRefPtrArray::GetData()
	{
		return m_impl.front();
	}

	ZRefPtrArray::data_t ZRefPtrArray::GetAt(int iIndex) const
	{
		if(iIndex>=0 && iIndex<m_impl.size())
			return m_impl.at(iIndex);
		else
			return NULL;
	}

	ZRefPtrArray::data_t ZRefPtrArray::operator[] (int iIndex) const
	{
		return GetAt(iIndex);
	}

	ZRefPtrArray::data_t ZRefPtrArray::Front()const
	{
		return m_impl.front();
	}

	ZRefPtrArray::data_t ZRefPtrArray::Back()const
	{
		return m_impl.back();
	}






	///////////////////////////////////////////////////////////////////////////////////////////////
	//hashmap
	struct ZStrHashMapImpl
	{
		UT_hash_handle hh;
		void* data;
		char key[1];
	};


	ZStrHashMap::ZStrHashMap()
		:m_impl(NULL)
	{
	}
	ZStrHashMap::~ZStrHashMap()
	{
		RemoveAll();
	}

	ZStrHashMap::data_t ZStrHashMap::Find(const char* key) const
	{
		ZStrHashMapImpl* val=NULL;
		HASH_FIND_STR( m_impl, key,val);
		if (val)
			return val->data;
		else
			return NULL;
	}

	void ZStrHashMap::Set(const char* key, data_t pData)
	{
		ZStrHashMapImpl* val=NULL;
		HASH_FIND_STR( m_impl, key,val);		
		if (val)
		{
			HASH_DEL(m_impl,val);
			zfree(val);
		}

		int keyLen=strlen(key);
		val = (struct ZStrHashMapImpl*)zmalloc(sizeof(struct ZStrHashMapImpl)+ keyLen*sizeof(char));
		val->data=pData;
		strcpy(val->key,key);
		HASH_ADD(hh,m_impl,key,keyLen,val);
	}

	bool ZStrHashMap::Remove(const char* key)
	{
		ZStrHashMapImpl* val=NULL;
		HASH_FIND_STR( m_impl, key,val);
		if(val)
		{
			HASH_DEL(m_impl,val);
			zfree(val);
			return true;
		}
		else
			return false;
	}


	void ZStrHashMap::RemoveAll()
	{
		if (!m_impl)
			return;
		ZStrHashMapImpl *val=NULL,*tmp=NULL;
		HASH_ITER(hh, m_impl, val, tmp) 
		{
			HASH_DEL(m_impl,val);
			zfree(val);
		}

		m_impl=NULL;
	}

	bool ZStrHashMap::Remove(Iterator* it)
	{
		if(it)
		{
			HASH_DEL(m_impl,it->m_data);
			zfree(it->m_data);
			return true;
		}
		else
			return false;
	}

	int ZStrHashMap::GetSize() const
	{
		return HASH_COUNT(m_impl);
	}

	ZStrHashMap::Iterator ZStrHashMap::Begin()
	{
		return Iterator(m_impl);
	}

	ZStrHashMap::Iterator ZStrHashMap::End()
	{
		return Iterator(NULL);
	}


	ZStrHashMap::Iterator::Iterator(ZStrHashMapImpl* data)
		:m_data(data)
	{
	}

	ZStrHashMap::Iterator::Iterator(const Iterator& rfs)
	{
		m_data=rfs.m_data;
	}

	ZStrHashMap::Iterator& ZStrHashMap::Iterator::operator++()
	{
		if(m_data)
			m_data=(struct ZStrHashMapImpl*)(m_data->hh.next);
		return *this;
	}

	bool ZStrHashMap::Iterator::operator==(const Iterator& rfs)
	{
		return m_data==rfs.m_data;
	}

	bool ZStrHashMap::Iterator::operator!=(const Iterator& rfs)
	{
		return m_data!=rfs.m_data;
	}

	ZStrHashMap::data_t ZStrHashMap::Iterator::operator*()
	{
		if(m_data)
			return m_data->data;
		else
			return NULL;
	}

	ZStrHashMap::data_t ZStrHashMap::Iterator::Data()
	{
		if(m_data)
			return m_data->data;
		else
			return NULL;
	}

	void ZStrHashMap::Iterator::SetData(data_t data)
	{
		m_data->data=data;
	}

	const char* ZStrHashMap::Iterator::Key()
	{
		if(m_data)
			return m_data->key;
		else
			return NULL;
	}


	/////////////////////////////////////////////////////////////////////////////////////////
	//hashmap
	struct ZRefStrHashMapImpl
	{
		UT_hash_handle hh;
		ZRefCountedBase* data;
		char key[1];
	};


	ZRefStrHashMap::ZRefStrHashMap()
		:m_impl(NULL)
	{
	}
	ZRefStrHashMap::~ZRefStrHashMap()
	{
		RemoveAll();
	}

	ZRefStrHashMap::data_t ZRefStrHashMap::Find(const char* key) const
	{
		ZRefStrHashMapImpl* val=NULL;
		HASH_FIND_STR( m_impl, key,val);
		if (val)
			return val->data;
		else
			return NULL;
	}

	void ZRefStrHashMap::Set(const char* key, data_t pData)
	{
		ZRefStrHashMapImpl* val=NULL;
		HASH_FIND_STR( m_impl, key,val);		
		if (val)
		{
			HASH_DEL(m_impl,val);
			if(val->data)
				val->data->Release();
			zfree(val);
		}

		int keyLen=strlen(key);
		val = (struct ZRefStrHashMapImpl*)zmalloc(sizeof(struct ZRefStrHashMapImpl)+ keyLen*sizeof(char));
		val->data=pData;
		if(val->data)
			val->data->AddRef();
		strcpy(val->key,key);
		HASH_ADD(hh,m_impl,key,keyLen,val);
	}

	bool ZRefStrHashMap::Remove(const char* key)
	{
		ZRefStrHashMapImpl* val=NULL;
		HASH_FIND_STR( m_impl, key,val);
		if(val)
		{
			HASH_DEL(m_impl,val);
			if(val->data)
				val->data->Release();
			zfree(val);
			return true;
		}
		else
			return false;
	}


	void ZRefStrHashMap::RemoveAll()
	{
		if (!m_impl)
			return;
		ZRefStrHashMapImpl *val=NULL,*tmp=NULL;
		HASH_ITER(hh, m_impl, val, tmp) 
		{
			HASH_DEL(m_impl,val);
			if(val->data)
				val->data->Release();
			zfree(val);
		}
		m_impl=NULL;
	}


	int ZRefStrHashMap::GetSize() const
	{
		return HASH_COUNT(m_impl);
	}

	ZRefStrHashMap::Iterator ZRefStrHashMap::Begin()
	{
		return Iterator(m_impl);
	}

	ZRefStrHashMap::Iterator ZRefStrHashMap::End()
	{
		return Iterator(NULL);
	}


	ZRefStrHashMap::Iterator::Iterator(ZRefStrHashMapImpl* data)
		:m_data(data)
	{
	}

	ZRefStrHashMap::Iterator::Iterator(const Iterator& rfs)
	{
		m_data=rfs.m_data;
	}

	ZRefStrHashMap::Iterator& ZRefStrHashMap::Iterator::operator++()
	{
		if(m_data)
			m_data=(struct ZRefStrHashMapImpl*)(m_data->hh.next);
		return *this;
	}

	bool ZRefStrHashMap::Iterator::operator==(const Iterator& rfs)
	{
		return m_data==rfs.m_data;
	}

	bool ZRefStrHashMap::Iterator::operator!=(const Iterator& rfs)
	{
		return m_data!=rfs.m_data;
	}

	ZRefStrHashMap::data_t ZRefStrHashMap::Iterator::operator*()
	{
		if(m_data)
			return m_data->data;
		else
			return NULL;
	}

	ZRefStrHashMap::data_t ZRefStrHashMap::Iterator::Data()
	{
		if(m_data)
			return m_data->data;
		else
			return NULL;
	}

	const char* ZRefStrHashMap::Iterator::Key()
	{
		if(m_data)
			return m_data->key;
		else
			return NULL;
	}


	///////////////////////////////////////////////////////////////////////////////////////////////
	//hashmap
	struct ZIntHashMapImpl
	{
		UT_hash_handle hh;
		void* data;
		unsigned int key;
	};


	ZIntHashMap::ZIntHashMap()
		:m_impl(NULL)
	{
	}
	ZIntHashMap::~ZIntHashMap()
	{
		RemoveAll();
	}

	ZIntHashMap::data_t ZIntHashMap::Find(key_t key) const
	{
		ZIntHashMapImpl* val=NULL;
		HASH_FIND_INT( m_impl, &key,val);
		if (val)
			return val->data;
		else
			return NULL;
	}

	void ZIntHashMap::Set(key_t key, data_t pData)
	{
		ZIntHashMapImpl* val=NULL;
		HASH_FIND_INT( m_impl, &key,val);	
		if (val)
		{
			HASH_DEL(m_impl,val);
			zfree(val);
		}
		val = (struct ZIntHashMapImpl*)zmalloc(sizeof(struct ZIntHashMapImpl));
		val->data=pData;
		val->key=key;
		HASH_ADD_INT(m_impl,key,val);
	}

	bool ZIntHashMap::Remove(key_t key)
	{
		ZIntHashMapImpl* val=NULL;
		HASH_FIND_INT( m_impl, &key,val);
		if(val)
		{
			HASH_DEL(m_impl,val);
			zfree(val);
			return true;
		}
		else
			return false;
	}


	void ZIntHashMap::RemoveAll()
	{
		if (!m_impl)
			return;
		ZIntHashMapImpl *val=NULL,*tmp=NULL;
		HASH_ITER(hh, m_impl, val, tmp) 
		{
			HASH_DEL(m_impl,val);
			zfree(val);
		}
		m_impl=NULL;
	}

	bool ZIntHashMap::Remove(Iterator* it)
	{
		if(it)
		{
			HASH_DEL(m_impl,it->m_data);
			zfree(it->m_data);
			return true;
		}
		else
			return false;
	}

	int ZIntHashMap::GetSize() const
	{
		return HASH_COUNT(m_impl);
	}

	ZIntHashMap::Iterator ZIntHashMap::Begin()
	{
		return Iterator(m_impl);
	}

	ZIntHashMap::Iterator ZIntHashMap::End()
	{
		return Iterator(NULL);
	}


	ZIntHashMap::Iterator::Iterator(ZIntHashMapImpl* data)
		:m_data(data)
	{
	}

	ZIntHashMap::Iterator::Iterator(const Iterator& rfs)
	{
		m_data=rfs.m_data;
	}

	ZIntHashMap::Iterator& ZIntHashMap::Iterator::operator++()
	{
		if(m_data)
			m_data=(struct ZIntHashMapImpl*)(m_data->hh.next);
		return *this;
	}

	bool ZIntHashMap::Iterator::operator==(const Iterator& rfs)
	{
		return m_data==rfs.m_data;
	}

	bool ZIntHashMap::Iterator::operator!=(const Iterator& rfs)
	{
		return m_data!=rfs.m_data;
	}

	ZIntHashMap::data_t ZIntHashMap::Iterator::operator*()
	{
		if(m_data)
			return m_data->data;
		else
			return NULL;
	}

	ZIntHashMap::data_t ZIntHashMap::Iterator::Data()
	{
		if(m_data)
			return m_data->data;
		else
			return NULL;
	}

	void ZIntHashMap::Iterator::SetData(data_t data)
	{
		m_data->data=data;
	}

	ZIntHashMap::key_t ZIntHashMap::Iterator::Key()
	{
		if(m_data)
			return m_data->key;
		else
			return 0;
	}


	/////////////////////////////////////////////////////////////////////////////////////////
	//hashmap
	struct ZRefIntHashMapImpl
	{
		UT_hash_handle hh;
		ZRefCountedBase* data;
		unsigned int key;
	};


	ZRefIntHashMap::ZRefIntHashMap()
		:m_impl(NULL)
	{
	}
	ZRefIntHashMap::~ZRefIntHashMap()
	{
		RemoveAll();
	}

	ZRefIntHashMap::data_t ZRefIntHashMap::Find(key_t key) const
	{
		ZRefIntHashMapImpl* val=NULL;
		HASH_FIND_INT( m_impl, &key,val);
		if (val)
			return val->data;
		else
			return NULL;
	}

	void ZRefIntHashMap::Set(key_t key, data_t pData)
	{

		if (key == 75)
		{
			int dsad=0;
		}
		ZRefIntHashMapImpl* val=NULL;
		HASH_FIND_INT( m_impl, &key,val);	
		if (val)
		{
			HASH_DEL(m_impl,val);
			if(val->data)
				val->data->Release();
			zfree(val);
		}
		val = (struct ZRefIntHashMapImpl*)zmalloc(sizeof(struct ZRefIntHashMapImpl));
		val->data=pData;
		val->key=key;
		if(val->data)
			val->data->AddRef();
		HASH_ADD_INT(m_impl,key,val);
	}

	bool ZRefIntHashMap::Remove(key_t key)
	{
		ZRefIntHashMapImpl* val=NULL;
		HASH_FIND_INT( m_impl, &key,val);
		if(val)
		{
			HASH_DEL(m_impl,val);
			if(val->data)
				val->data->Release();
			zfree(val);
			return true;
		}
		else
			return false;
	}


	void ZRefIntHashMap::RemoveAll()
	{
		if (!m_impl)
			return;
		ZRefIntHashMapImpl *val=NULL,*tmp=NULL;
		HASH_ITER(hh, m_impl, val, tmp) 
		{
			HASH_DEL(m_impl,val);
			if(val->data)
				val->data->Release();
			zfree(val);
		}
		m_impl=NULL;
	}


	int ZRefIntHashMap::GetSize() const
	{
		return HASH_COUNT(m_impl);
	}

	ZRefIntHashMap::Iterator ZRefIntHashMap::Begin()
	{
		return Iterator(m_impl);
	}

	ZRefIntHashMap::Iterator ZRefIntHashMap::End()
	{
		return Iterator(NULL);
	}


	ZRefIntHashMap::Iterator::Iterator(ZRefIntHashMapImpl* data)
		:m_data(data)
	{
	}

	ZRefIntHashMap::Iterator::Iterator(const Iterator& rfs)
	{
		m_data=rfs.m_data;
	}

	ZRefIntHashMap::Iterator& ZRefIntHashMap::Iterator::operator++()
	{
		if(m_data)
			m_data=(struct ZRefIntHashMapImpl*)(m_data->hh.next);
		return *this;
	}

	bool ZRefIntHashMap::Iterator::operator==(const Iterator& rfs)
	{
		return m_data==rfs.m_data;
	}

	bool ZRefIntHashMap::Iterator::operator!=(const Iterator& rfs)
	{
		return m_data!=rfs.m_data;
	}

	ZRefIntHashMap::data_t ZRefIntHashMap::Iterator::operator*()
	{
		if(m_data)
			return m_data->data;
		else
			return NULL;
	}

	ZRefIntHashMap::data_t ZRefIntHashMap::Iterator::Data()
	{
		if(m_data)
			return m_data->data;
		else
			return NULL;
	}

	ZRefIntHashMap::key_t ZRefIntHashMap::Iterator::Key()
	{
		if(m_data)
			return m_data->key;
		else
			return 0;
	}





} // namespace DuiLib
